package com.summer.bilibili.util;

import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Optional;

/**
 * Servlet工具类 - 提供HTTP请求和响应的快捷操作方法
 * 核心原理：通过Spring的RequestContextHolder获取当前线程绑定的请求上下文
 */
public class ServletUtils {
    /**
     * 获取当前线程绑定的ServletRequestAttributes对象
     * 实现原理：Spring通过ThreadLocal存储每个请求的上下文信息
     * 注意事项：在非Web请求线程中调用将返回null
     *
     * @return ServletRequestAttributes 当前请求的上下文属性对象
     */
    public static ServletRequestAttributes getRequestAttributes () {
        // 从ThreadLocal中获取当前请求的RequestAttributes对象
        // 并强制转换为Servlet专用的ServletRequestAttributes类型
        return (ServletRequestAttributes) RequestContextHolder.getRequestAttributes ( );
    }

    /**
     * 获取当前HTTP请求对象(HttpServletRequest)
     * 依赖关系：通过getRequestAttributes()获取上下文后再获取请求对象
     * 风险点：如果当前不在Web请求上下文中，将抛出NullPointerException
     *
     * @return HttpServletRequest 当前HTTP请求对象
     */
    public static HttpServletRequest getRequest () {
        // 从请求上下文中提取HttpServletRequest对象
        return getRequestAttributes ( ).getRequest ( );
    }

    /**
     * 获取当前HTTP响应对象(HttpServletResponse)
     * 使用场景：需要直接操作响应时使用（如设置header）
     *
     * @return HttpServletResponse 当前HTTP响应对象
     */
    public static HttpServletResponse getResponse () {
        // 从请求上下文中提取HttpServletResponse对象
        return getRequestAttributes ( ).getResponse ( );
    }

    /**
     * 获取请求参数值（单值参数）
     * 工作原理：底层调用request.getParameter()
     * 注意：对于多值参数只会返回第一个值
     *
     * @param parameterName 参数名称
     * @return 参数值，如果不存在则返回null
     */
    public static String getParameter ( String parameterName ) {
        return getRequest ( ).getParameter ( parameterName );
    }

    /**
     * 获取请求参数值（带默认值）
     * 优化点：当参数不存在时返回指定的默认值，避免空指针
     *
     * @param parameterName 参数名称
     * @param defaultValue  参数不存在时返回的默认值
     * @return 参数值或默认值
     */
    public static String getParameter ( String parameterName , String defaultValue ) {
        String value = getRequest ( ).getParameter ( parameterName );
        return value == null ? defaultValue : value;
    }

    /**
     * 获取布尔类型请求参数
     * 转换逻辑：使用Boolean.parseBoolean转换字符串
     * 特殊处理：当参数不存在时使用默认值转换
     *
     * @param parameterName 参数名称
     * @param defaultValue  参数不存在时的默认布尔值
     * @return 解析后的布尔值
     */
    public static boolean getBoolParameter ( String parameterName , boolean defaultValue ) {
        String value = getParameter ( parameterName , defaultValue + "" );
        return Boolean.parseBoolean ( value );
    }

    /**
     * 设置请求参数值（危险操作）
     * 严重警告：Servlet规范要求parameterMap是只读的
     * 实际效果：在标准Servlet实现中会抛出UnsupportedOperationException
     *
     * @param parameterName 参数名称
     * @param value         要设置的参数值数组
     */
    public static void setParameter ( String parameterName , String[] value ) {
        getRequest ( ).getParameterMap ( ).put ( parameterName , value );
    }

    /**
     * 获取请求属性值（带默认值）
     * 优化技巧：使用Optional优雅处理null值情况
     *
     * @param attributeName 属性名称
     * @param defaultValue  属性不存在时的默认值
     * @return 属性值或默认值
     */
    public static Object getAttribute ( String attributeName , Object defaultValue ) {
        return Optional.ofNullable ( getRequest ( ).getAttribute ( attributeName ) ).orElse ( defaultValue );
    }

    /**
     * 设置请求属性值
     * 作用域：设置的值仅在当前请求范围内有效
     * 典型应用：在请求处理链中传递数据
     *
     * @param attributeName 属性名称
     * @param value         要设置的属性值
     */
    public static void setAttribute ( String attributeName , Object value ) {
        getRequest ( ).setAttribute ( attributeName , value );
    }
}
